﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using MarqueeMoment.Entities;
using NLog;
using System.IO;
using MarqueeMoment.CameraController;
using EDSDKLib;
using System.Collections;
using MarqueeMoment.CameraController.Camera;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;


namespace MarqueeMoment.Forms
{
    public partial class frmTakePhoto : Form, Observer
    {
        #region User defined variables

        private static Logger logger = LogManager.GetCurrentClassLogger();
        private bool _backFromReview = false;
        public bool isCameraDetected = false;

        #endregion User defined variables

        #region Constructor

        public frmTakePhoto(Boolean incrementIndex)
        {
            logger.Info("On frmTakePhoto(Boolean incrementIndex) with incrementIndex:" + incrementIndex.ToString());
            InitializeComponent();

            //Increment ImageIndex
            if (incrementIndex)
                Common.imageIndex++;
            else
                InitializeGridList();

            frmTakePhotoInstance = this;
            InitializeValues();
        }

        public frmTakePhoto(Boolean incrementIndex, bool backFromReview)
        {
            logger.Info("On frmTakePhoto(Boolean incrementIndex, bool backFromReview) with incrementIndex:" + incrementIndex.ToString() + " backFromReview:" + backFromReview.ToString());
            InitializeComponent();
            _backFromReview = backFromReview;

            //Increment ImageIndex
            if (incrementIndex)
                Common.imageIndex++;
            else
                InitializeGridList();

            frmTakePhotoInstance = this;
            InitializeValues();
        }

        #endregion Constructor

        #region "User defined attributes"

        //// Save as class variable, new delegates of event handlers.

        public EDSDK.EdsPropertyEventHandler inPropertyEventHandler = new EDSDK.EdsPropertyEventHandler(CameraEventListener.handlePropertyEvent);
        public EDSDK.EdsObjectEventHandler inObjectEventHandler = new EDSDK.EdsObjectEventHandler(CameraEventListener.handleObjectEvent);
        public EDSDK.EdsStateEventHandler inStateEventHandler = new EDSDK.EdsStateEventHandler(CameraEventListener.handleStateEvent);
        //
        public static CameraController.Camera.CameraController controller;
        public static CameraModel model;
        public static frmTakePhoto frmTakePhotoInstance;

        public static Hashtable m_cmbTbl = new Hashtable();

        IntPtr camera = IntPtr.Zero;
        Boolean isSDKLoaded = false;

        #endregion

        #region User Defined Methods

        public static void OnPictureDownloaded()
        {
            logger.Info("On OnPictureDownloaded()");
            frmTakePhotoInstance.timerPicLoad.Enabled = true;
        }

        public static void UpdateSpinner(bool spinnerStatus)
        {
            logger.Info("On UpdateSpinner(bool spinnerStatus) with spinnerStatus:" + spinnerStatus.ToString());
            if (frmTakePhotoInstance.m_spinnerpicture.InvokeRequired)
                frmTakePhotoInstance.m_spinnerpicture.Invoke(new UpdateSpinnerCallback(UpdateSpinner), new object[] { spinnerStatus });

            if (frmTakePhotoInstance.m_spinnerpicture.Visible != spinnerStatus)
                frmTakePhotoInstance.m_spinnerpicture.Visible = spinnerStatus;
        }

        public delegate void UpdateSpinnerCallback(bool spinnerStatus);

        public void UpdateCounterText(String counterText)
        {
            logger.Info("On UpdateCounterText(String counterText) with counterText:" + counterText);
            if (btnTakePicture.InvokeRequired)
                btnTakePicture.Invoke(new UpdateCounterTextCallback(UpdateCounterText), new object[] { counterText });

            if (btnTakePicture.Text != counterText)
                btnTakePicture.Text = counterText;
        }

        public delegate void UpdateCounterTextCallback(string counterText);       
        
        private void ClearBinDirImage(String dirPath)
        {
            logger.Info("On ClearBinDirImage(String dirPath) with dirPath:" + dirPath);
            try
            {
                if (Directory.Exists(dirPath))
                {
                    String[] strFilesName = System.IO.Directory.GetFiles(dirPath);
                    if (strFilesName.Count() > 0)
                    {
                        foreach (string filename in strFilesName)
                        {
                            FileInfo file = new FileInfo(filename);

                            if (file.Extension.ToUpper().Contains("JPG") || file.Extension.ToUpper().Contains("JPEG") || file.Extension.ToUpper().Contains("PNG") || file.Extension.ToUpper().Contains("GIF"))
                            {
                                File.Delete(file.Name);
                            }
                            file = null;
                        }
                    }
                    strFilesName = null;
                }
            }
            catch (Exception exc)
            {
                logger.Error(exc.StackTrace);
            }

        }

        private ArrayList GetImageFileFromDir(String dirPath)
        {
            logger.Info("On GetImageFileFromDir(String dirPath) with dirPath:" + dirPath);
            ArrayList imageFiles = new ArrayList();
            if (Directory.Exists(dirPath))
            {
                String[] strFilesName = System.IO.Directory.GetFiles(dirPath);
                if (strFilesName.Count() > 0)
                {
                    foreach (string filename in strFilesName)
                    {
                        FileInfo file = new FileInfo(filename);

                        if (file.Extension.ToUpper().Contains("JPG") || file.Extension.ToUpper().Contains("JPEG") || file.Extension.ToUpper().Contains("PNG") || file.Extension.ToUpper().Contains("GIF"))
                        {
                            imageFiles.Add(filename);
                        }
                        file = null;

                    }
                }
                strFilesName = null;
            }
            return imageFiles;
        }

        /// <summary>
        /// Set Review Button Enable
        /// </summary>
        /// <param name="enabled">boolean value</param>
        private void SetReviewButtonEnable(bool enabled)
        {
            if (btnReviewPhoto.Enabled != enabled)
            {
                btnReviewPhoto.Enabled = enabled;
                if (enabled)
                    this.btnReviewPhoto.BackgroundImage = global::MarqueeMoment.Properties.Resources.view_photos_bttn_595_512;
                else
                    this.btnReviewPhoto.BackgroundImage = global::MarqueeMoment.Properties.Resources.view_photos_disable_bttn_595_512;
            }
        }

        /// <summary>
        /// Set TakePicture Button Enable
        /// </summary>
        /// <param name="enabled">boolean value</param>
        private void SetTakePictureButtonEnable(bool enabled)
        {
            btnTakePicture.Enabled = enabled;
            if (enabled)
                this.btnTakePicture.BackgroundImage = global::MarqueeMoment.Properties.Resources.take_picture_bttn_324_512;
            else
                this.btnTakePicture.BackgroundImage = global::MarqueeMoment.Properties.Resources.take_picture_disable_bttn_324_512;
        }

        private void InitializeGridList()
        {
            logger.Info("On InitializeGridList()");
            try
            {
                if (!Directory.Exists(Common.capturedPhotoDirPath))
                    Directory.CreateDirectory(Common.capturedPhotoDirPath);


                String dirPath = string.Empty;
                if (_backFromReview)
                    dirPath = Common.capturedPhotoDirPath;
                else
                    dirPath = System.Windows.Forms.Application.StartupPath + @"\";

                logger.Info("On InitializeGridList(), search for images in Dir:" + dirPath);
                ArrayList strFilesName = GetImageFileFromDir(dirPath);

                if (strFilesName.Count > 0)
                {
                    logger.Info("On InitializeGridList(), Total images in Dir:" + strFilesName.Count.ToString());
                    if (_backFromReview)
                    {
                        int rowIndex = 0;
                        for (Int32 count = 0; count < strFilesName.Count; count++)
                        {
                            String fileName = "Photo" + Common.imageIndex;
                            if (strFilesName[count].ToString().Contains(fileName))
                            {
                                Bitmap tempImage = new Bitmap(strFilesName[count].ToString());
                                Bitmap img = new Bitmap(tempImage);
                                tempImage.Dispose();

                                dgImage.Rows.Add();
                                dgImage.Rows[rowIndex].Cells["IdCol"].Value = string.Empty;
                                dgImage.Rows[rowIndex].Cells["ImageData"].Value = img;
                                rowIndex++;
                            }
                        }
                    }
                    else
                    {
                        String photoName = "Photo" + Common.imageIndex;
                        photoName += (dgImage.Rows.Count + 1) + ".Jpg";
                        photoName = Common.capturedPhotoDirPath + photoName;

                        int rowIndex = 0;
                        for (Int32 count = 0; count < strFilesName.Count; count++)
                        {
                            String fileName = "Captured_MM_";
                            if (strFilesName[count].ToString().Contains(fileName))
                            {
                                File.Copy(strFilesName[rowIndex].ToString(), photoName, true);
                                File.Delete(strFilesName[rowIndex].ToString());

                                if (File.Exists(photoName))
                                {
                                    Bitmap tempImage = new Bitmap(photoName);
                                    Bitmap img = new Bitmap(tempImage);
                                    tempImage.Dispose();

                                    dgImage.Rows.Add();
                                    dgImage.Rows[dgImage.Rows.Count - 1].Cells["IdCol"].Value = string.Empty;
                                    dgImage.Rows[dgImage.Rows.Count - 1].Cells["ImageData"].Value = img;
                                }
                                break;
                            }
                            rowIndex++;
                        }
                    }
                }
                strFilesName.Clear();

                if (dgImage.RowCount > 0 && btnReviewPhoto.Enabled==false)
                    SetReviewButtonEnable(true);                
                else if (dgImage.RowCount == 0 && btnReviewPhoto.Enabled)
                    SetReviewButtonEnable(false);
                
            }
            catch (Exception exc)
            {
                logger.Error(exc.StackTrace);
                frmTakePhotoInstance.timerPicLoad.Enabled = false;
                logger.Info("disabled timerPicLoad, because of error");
                Dialogs.Error("Error on showing Capture Photos list");
            }
        }

        /// <summary>
        /// For releasing image from picture box
        /// </summary>
        private void ReleaseSource()
        {
            logger.Info("On ReleaseSource() , releasing picturebox and data grid");
            if (picboxPhoto.Image != null)
            {
                picboxPhoto.Image.Dispose();
                picboxPhoto.Image = null;
            }

            if (dgImage != null)
            {
                dgImage.Rows.Clear();
                dgImage.Dispose();
            }
        }

        /// <summary>
        /// For releasing Camera and SDK
        /// </summary>
        private void ReleaseCamera()
        {
            logger.Info("On ReleaseCamera()");

            isCameraDetected = false;
            logger.Info("set isCameraDetected to false");
            if (controller != null && frmTakePhotoInstance.m_spinnerpicture.Visible == false)
                controller.actionPerformed("close");

            if (camera != null && camera != IntPtr.Zero)
            {
                uint err = EDSDK.EdsRelease(camera);
                logger.Info("On ReleaseCamera(), EDSDK.EdsRelease(camera)--> returns err=" + err.ToString() + " with Camera:" + camera.ToString());
                camera = IntPtr.Zero;
            }

            if ((isSDKLoaded))
            {
      //          uint err = EDSDK.EdsTerminateSDK();
     //           logger.Info("On ReleaseCamera(), EDSDK.EdsTerminateSDK()--> returns err=" + err.ToString());
                isSDKLoaded = false;
            }

            if (model != null)
            {
                model = null;
            }


            if (controller != null)
            {
                controller = null;
            }
        }

        public static void ShowLiveView()
        {
            frmTakePhotoInstance.PreviewOn();
        }

        private bool DetectCamera()
        {
            logger.Info("On DetectCamera()");
            uint err = EDSDK.EDS_ERR_OK;
            IntPtr cameraList = IntPtr.Zero;
            Int32 count = 0;

       //     err = EDSDK.EdsInitializeSDK();
            logger.Info("On DetectCamera(), EDSDK.EdsInitializeSDK()--> returns err=" + err.ToString());
                
            if (err == EDSDK.EDS_ERR_OK)
                isSDKLoaded = true;

            if (err == EDSDK.EDS_ERR_OK)
      //          err = EDSDK.EdsGetCameraList(out cameraList);
            logger.Info("On DetectCamera(), EDSDK.EdsGetCameraList(out cameraList)--> returns err=" + err.ToString() + " with cameraList:" + cameraList.ToString());
            

            if (err == EDSDK.EDS_ERR_OK)
            {
      //          err = EDSDK.EdsGetChildCount(cameraList, out count);
                if (count == 0)
                {
                    err = EDSDK.EDS_ERR_DEVICE_NOT_FOUND;
                }
                logger.Info("On DetectCamera(), EDSDK.EdsGetChildCount(cameraList, out count);--> returns err=" + err.ToString() + " with count:" + count.ToString());
            
            }

            //// Get the first camera.
            if (err == EDSDK.EDS_ERR_OK)
            {
                err = EDSDK.EdsGetChildAtIndex(cameraList, 0, out camera);

            }
            logger.Info("On DetectCamera(), Get the first camera, EDSDK.EdsGetChildAtIndex(cameraList, 0, out camera)--> returns err=" + err.ToString());
            

            EDSDK.EdsDeviceInfo deviceInfo = new EDSDK.EdsDeviceInfo();//EDSDK.EdsDeviceInfo deviceInfo = null;
            if (err == EDSDK.EDS_ERR_OK)
            {
                err = EDSDK.EdsGetDeviceInfo(camera, out deviceInfo);
                logger.Info("On DetectCamera(), EDSDK.EdsGetDeviceInfo(camera, out deviceInfo)--> returns err=" + err.ToString() + " with deviceInfo: " + deviceInfo.ToString());
            
                if (err == EDSDK.EDS_ERR_OK & camera == null)
                {
                    err = EDSDK.EDS_ERR_DEVICE_NOT_FOUND;
                    logger.Error("On DetectCamera(), If camera is null, set err=EDSDK.EDS_ERR_DEVICE_NOT_FOUND");
                }

            }

            if (cameraList != null)
            {
     //           EDSDK.EdsRelease(cameraList);
            }

            //// Create the camera model 
            if (err == EDSDK.EDS_ERR_OK)
            {
                model = cameraModelFactory(camera, deviceInfo);

                if (model == null)
                {
                    err = EDSDK.EDS_ERR_DEVICE_NOT_FOUND;
                    logger.Error("On DetectCamera(), Create the camera model, if model==null then set err = EDSDK.EDS_ERR_DEVICE_NOT_FOUND");
                }
            }

            if (err != EDSDK.EDS_ERR_OK)
            {
                logger.Info("On DetectCamera(), Cannot detect camera");
                MessageBox.Show("Cannot detect camera");

            }


            if (err == EDSDK.EDS_ERR_OK)
            {
                //// Create a controller
                controller = new CameraController.Camera.CameraController();
                logger.Info("On DetectCamera(), Create a controller");
               
                //// Set the model to this controller.
                controller.setCameraModel(model);
                logger.Info("On DetectCamera(), Set the model to this controller");
               
                //// Make notify the model updating to the view.
                model.addObserver(this);
                logger.Info("On DetectCamera(), Make notify the model updating to the view");
               
                // ------------------------------------------------------------------------
                // ------------------------------------------------------------------------
                // You should create class instance of delegates of event handlers 
                // with 'new' expressly if its attribute is Shared, 
                // because System sometimes do garbage-collect these delegates.
                //
                //
                // This error occurs.
                //
                // CallbackOnCollectedDelegate is detected.
                // Message: Callback was called with
                // garbage-collected delegate of  
                // Type() 'VBSample3!VBSample3.EDSDKTypes+EdsPropertyEventHandler::Invoke' 
                // 
                // It will be able to make data loss or application clash.
                // You should stock delegates when you want to send delegate to unmanaged code.
                //
                // ------------------------------------------------------------------------

                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = EDSDK.EdsSetPropertyEventHandler(camera, EDSDK.PropertyEvent_All, inPropertyEventHandler, IntPtr.Zero);
                    logger.Info("On DetectCamera(), EDSDK.EdsSetPropertyEventHandler(camera, EDSDK.PropertyEvent_All, inPropertyEventHandler, IntPtr.Zero)--> returns err=" + err.ToString());
                }

                //// Set ObjectEventHandler
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = EDSDK.EdsSetObjectEventHandler(camera, EDSDK.ObjectEvent_All, inObjectEventHandler, IntPtr.Zero);
                    logger.Info("On DetectCamera(), EDSDK.EdsSetObjectEventHandler(camera, EDSDK.ObjectEvent_All, inObjectEventHandler, IntPtr.Zero)--> returns err=" + err.ToString());
                }

                //// Set StateEventHandler
                if (err == EDSDK.EDS_ERR_OK)
                {
                    err = EDSDK.EdsSetCameraStateEventHandler(camera, EDSDK.StateEvent_All, inStateEventHandler, IntPtr.Zero);
                    logger.Info("On DetectCamera(), EDSDK.EdsSetCameraStateEventHandler(camera, EDSDK.StateEvent_All, inStateEventHandler, IntPtr.Zero)--> returns err=" + err.ToString());
                }

            }

            if (err != EDSDK.EDS_ERR_OK)
            {
                logger.Error("On DetectCamera(), Calling Release Camera() because of err=" + err.ToString());
                ReleaseCamera();
                return false;
            }

            ////Execute the controller.
            controller.run();

            return true;
        }


        public delegate void UpdateDelegate(Observable @from, uint msg, uint data);


        public void UpdateWindow(Observable @from, uint msg, uint data)
        {
            //Get the name of this thread.
            string threadName = System.Threading.Thread.CurrentThread.Name;

            //// Make this form be able to be updated by other thread.
            if (InvokeRequired)
            {
                //Create UpdateDelegate
                UpdateDelegate dlg = new UpdateDelegate(UpdateWindow);
                try
                {
                    BeginInvoke(dlg, new object[] {
					@from,
					msg,
					data
				});
                }
                catch (Exception e)
                {
                    return;
                }
                finally
                {
                }
                return;
            }
        }
        void Observer.update(Observable @from, uint msg, uint data)
        {
            UpdateWindow(@from, msg, data);
        }


        public CameraModel cameraModelFactory(IntPtr camera, EDSDK.EdsDeviceInfo deviceInfo)
        {

            // if Legacy protocol.
            if (deviceInfo.DeviceSubType == 0)
            {
                return new CameraModelLegacy(camera);
            }

            // PTP protocol.
            return new CameraModel(camera);

        }

        private bool IsImageInUsed(String imagePath)
        {
            if (!File.Exists(imagePath))
                return true;
            try
            {
                Image checkImageAvailable = Image.FromFile(imagePath);
                if (checkImageAvailable != null)
                    checkImageAvailable.Dispose();

                checkImageAvailable = null;
                return false;
            }
            catch (Exception exc)
            {
            }

            return true;

        }

        /// <summary>
        /// To Initialize Values
        /// </summary>
        private void InitializeValues()
        {
            logger.Info("On InitializeValues()at frmTakePhoto form");
            ShowTime();
            //MessageBox.Show(String.Format("{0:x2}", 129));
            //MessageBox.Show(EDSDK.EDS_ERR_NOT_SUPPORTED.ToString());


            //Delete existing image
            String dirPath = System.Windows.Forms.Application.StartupPath + @"\";
            logger.Info("Deleting existing image from Dir: " + dirPath);
            ClearBinDirImage(dirPath);
            logger.Info("Cleared images from Dir: " + dirPath);

            if (!DetectCamera())
            {
                logger.Info("Camera Not Detected");
                isCameraDetected = false;
                this.Close();
                return;
            }


            Image spinnerImage = Image.FromFile(Common.spinnerBigImagePath);
            m_spinnerpicture.Image = spinnerImage;

            logger.Info("Camera Detected");
            isCameraDetected = true;
        }

        /// <summary>
        /// To Show Time on Time Box
        /// </summary>
        private void ShowTime()
        {
            String currentTime = String.Empty;
            var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
            currentTime = TimeZoneInfo.ConvertTime(DateTime.Now, timeZone).ToLongTimeString();
            lblPM.Text = currentTime.Substring(currentTime.Length - 2);
            currentTime = currentTime.Substring(0, currentTime.Length - 3);

            lblT8.Text = currentTime.Substring(currentTime.Length - 1);
            lblT7.Text = currentTime.Substring(currentTime.Length - 2, 1);
            lblT6.Text = currentTime.Substring(currentTime.Length - 3, 1);
            lblT5.Text = currentTime.Substring(currentTime.Length - 4, 1);
            lblT4.Text = currentTime.Substring(currentTime.Length - 5, 1);
            lblT3.Text = currentTime.Substring(currentTime.Length - 6, 1);
            lblT2.Text = currentTime.Substring(currentTime.Length - 7, 1);

            if (currentTime.Length == 7)
                lblT1.Text = String.Empty;
            else
                lblT1.Text = currentTime.Substring(currentTime.Length - 8, 1);
        }

        #endregion User Defined Methods

        #region System Events

        private void timerTakePhoto_Tick(object sender, EventArgs e)
        {
            ShowTime();
        }

        private void btnMainmenu_Click(object sender, EventArgs e)
        {
            logger.Info("On btnMenu_Click at frmTakePhoto form, stoping live view");
            //Stop Live View 
            LiveViewRunning = false;
            this.Close();
        }

        private void btnReviewPhoto_Click(object sender, EventArgs e)
        {
            if (dgImage != null && dgImage.RowCount > 0)
            {
                logger.Info("On btnReviewPhoto_Click at frmTakePhoto form");
                if (m_spinnerpicture.Visible)
                {
                    logger.Info("On btnReviewPhoto_Click() , action cancelled because m_spinnerpicture.Visible:" + m_spinnerpicture.Visible.ToString());
                    return;
                }
                logger.Info("On btnReviewPhoto_Click(), stoping live view and releasing camera");
                LiveViewRunning = false;
                ReleaseCamera();
                ReleaseSource();
                this.Visible = false;
                frmReviewPhotos obReviewPhotos = new frmReviewPhotos();
                obReviewPhotos.ShowDialog();
                this.Close();
            }
        }

        //Removed button in new design
        //private void btnEraseSession_Click(object sender, EventArgs e)
        //{
        //    logger.Info("On btnEraseSession_Click at frmTakePhoto form");
        //    if (m_spinnerpicture.Visible)
        //        return;

        //    //Increment ImageIndex
        //    Common.imageIndex++;
        //    dgImage.Rows.Clear();
        //    InitializeGridList();
        //}

        private void btnTakePicture_Click(object sender, EventArgs e)
        {
            logger.Info("On btnTakePicture_Click at frmTakePhoto form");
            String dirPath = System.Windows.Forms.Application.StartupPath + @"\";
            ClearBinDirImage(dirPath);

            _backFromReview = false;
            if (dgImage != null && dgImage.RowCount > 4)
            {
                Dialogs.Exclamation("You can't take more than 5 photos for single messages");
                return;
            }
            else if (m_spinnerpicture.Visible)
                return;
            else
            {
                //Start Background worker for take picture
                logger.Info("On btnTakePicture_Click() , check for bgWorker.IsBusy:" + bgWorker.IsBusy.ToString());
                if (bgWorker.IsBusy != true)
                {
                    //Set BlankImage on btnTakePicture
                    this.btnTakePicture.BackgroundImage = global::MarqueeMoment.Properties.Resources.blank_button;
                    picboxPhoto.Focus();
                    this.Enabled = false;

                    bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork_TakePicture);
                    bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_Completed_TakePicture);
                    bgWorker.RunWorkerAsync();
                }
            }
        }

        private void frmTakePhoto_FormClosing(object sender, FormClosingEventArgs e)
        {
            logger.Info("On frmTakePhoto_FormClosing at frmTakePhoto form");
            //Stop Live View 
            LiveViewRunning = false;
            ReleaseSource();
            ReleaseCamera();

        }

        private void timerPicLoad_Tick(object sender, EventArgs e)
        {
            logger.Info("On timerPicLoad_Tick at frmTakePhoto form");
            if (isCameraDetected == false)
            {
                frmTakePhotoInstance.timerPicLoad.Enabled = false;
                logger.Error("Camera not detected, disabled timerPicLoad");
                return;
            }

            if (picboxPhoto.Image != null)
            {
                picboxPhoto.Image.Dispose();
                picboxPhoto.Image = null;
            }

            String dirPath = System.Windows.Forms.Application.StartupPath + @"\";
            ArrayList strFilesName = GetImageFileFromDir(dirPath);
            if (strFilesName.Count > 0)
            {
                logger.Info("Check for Image availability at path:" + dirPath + " , after capturing photo from camera");
                bool isImageAvailable = false;
                while (!isImageAvailable)
                {
                    try
                    {
                        Image checkImageAvailable = Image.FromFile(strFilesName[0].ToString());
                        if (checkImageAvailable != null)
                            checkImageAvailable.Dispose();

                        checkImageAvailable = null;
                        isImageAvailable = true;

                    }
                    catch (Exception exc)
                    {

                    }
                }
                logger.Info("Image available: " + isImageAvailable.ToString());
               
                FileInfo file = new FileInfo(strFilesName[0].ToString());
                String savedFileName = file.FullName.Replace(file.Name, "Captured_MM_" + file.Name);
                file = null;
                Common.UpdatePhotoSize(strFilesName[0].ToString(), savedFileName);
                logger.Info("Updated PhotoSize, beforePath:" + strFilesName[0].ToString() + " AfterPath:" + savedFileName);
            
                InitializeGridList();
                logger.Info("Start live view");
            }
            strFilesName.Clear();
            strFilesName = null;

            frmTakePhotoInstance.timerPicLoad.Enabled = false;
            logger.Info("Starting live view");
            ShowLiveView();
        }

        private void btnCameraSwitch_Click(object sender, EventArgs e)
        {
            logger.Info("On btnCameraSwitch_Click");
            picboxPhoto.Focus();
            try
            {
                if (btnTakePicture.Enabled)
                {
                    logger.Info("On btnCameraSwitch_Click Action: DisarmCamera");

                    if (picboxPhoto.Image != null)
                    {
                        picboxPhoto.Image.Dispose();
                        picboxPhoto.Image = null;
                    }
                    picboxPhoto.Visible = false;
                    UpdateSpinner(false);

                    this.lblFormState.Image = global::MarqueeMoment.Properties.Resources.camera_standby_590_162;
                    this.btnCameraSwitch.BackgroundImage = global::MarqueeMoment.Properties.Resources.arm_camera_bttn_92_512;
                    SetTakePictureButtonEnable(false);
                }
                else
                {
                    logger.Info("On btnCameraSwitch_Click Action: ArmCamera");

                    picboxPhoto.Visible = true;

                    this.lblFormState.Image = global::MarqueeMoment.Properties.Resources.live_camera_view_589_162;
                    this.btnCameraSwitch.BackgroundImage = global::MarqueeMoment.Properties.Resources.disarm_camera_bttn_92_512;
                    SetTakePictureButtonEnable(true);
                }
            }
            catch (Exception exc)
            {
                logger.Error(exc.StackTrace);
            }

        }

        private void btnComposeMessage_Click(object sender, EventArgs e)
        {
            if (dgImage != null && dgImage.RowCount > 0 && dgImage.CurrentCell.RowIndex >= 0)
            {
                logger.Info("On btnComposeMessage_Click at frmTakePhoto form");
                if (m_spinnerpicture.Visible)
                {
                    logger.Info("On btnComposeMessage_Click(), action cancelled because m_spinnerpicture.Visible:True");
                    return;
                }
                String imagePath = Common.GetImagePath(dgImage.CurrentCell.RowIndex);
                if (File.Exists(imagePath))
                {
                    if (picboxPhoto.Image != null)
                    {
                        picboxPhoto.Image.Dispose();
                        picboxPhoto.Image = null;
                    }

                    Common.SaveUpdatedSizePhoto(imagePath, false);

                    //Stop Live View 
                    logger.Info("On btnComposeMessage_Click(), stoping live view");
                    LiveViewRunning = false;
                    ReleaseCamera();
                    ReleaseSource();
                    this.Visible = false;
                    frmComposeMessage obComposeMessage = new frmComposeMessage(true);
                    obComposeMessage.ShowDialog();
                    this.Close();
                }
            }
        }

        #endregion System Events
        
        #region LiveView

        static Boolean LiveViewRunning = false;
        private System.Threading.Thread LVThread;

        //public static CameraModel model;// Edited by zoeb

        public void PreviewOn()
        {
            LVThread = new System.Threading.Thread(LiveView);

            LiveViewRunning = true;

            LVThread.Start();

        }

        internal void LiveView()
        {
            try
            {
                while (LiveViewRunning)
                {
                    // download a live view  
                    IntPtr pStream = default(IntPtr);
                    IntPtr pImageEvf = default(IntPtr);
                    IntPtr pCamera = default(IntPtr);
                    uint result = 0;
                    pCamera = model.getCameraObject();
                    uint device = 0;

                    if (!LiveViewRunning)
                        return;

                    // Get the output device for the live view image
                    result = EDSDK.EdsGetPropertyData(pCamera, EDSDK.PropID_Evf_OutputDevice, 0, out device);
                    Debug.WriteLineIf(result != EDSDK.EDS_ERR_OK, String.Format("Get Property Data failed: {0:X}", result));
                    Debug.WriteLineIf(result == EDSDK.EDS_ERR_OK, String.Format("Liveview output is: {0:x}", device));

                    // Set the computer as live view destination
                    if (result == EDSDK.EDS_ERR_OK)
                    {
                        result = EDSDK.EdsSetPropertyData(pCamera, EDSDK.PropID_Evf_OutputDevice, 0,
                            Marshal.SizeOf(EDSDK.EvfOutputDevice_PC), EDSDK.EvfOutputDevice_PC);
                        Debug.WriteLine(String.Format("Liveview output to computer: {0:X}", result));
                    }

                    if (!LiveViewRunning)
                        return;

                    result = EDSDK.EdsCreateMemoryStream(0, out pStream);
                    if (EDSDK.EDS_ERR_OK != result)
                    {
                        //Program.log(LogCategory.[Error], "Unable to create a memory stream:{0:X}", result)  
                        //MessageBox.Show("Unable to create a memory stream")  
                        logger.Error("On LiveView(), EDSDK.EdsCreateMemoryStream(0, out pStream)--> returns err=" + result.ToString());
                        ////////Dialogs.Error("EdsCreateMemoryStream failed");

                        UpdateSpinner(false);
                        return;
                    }

                    if (picboxPhoto.Image == null)
                    {
                        Thread.Sleep(1000);
                        UpdateSpinner(false);
                    }

                    if (!LiveViewRunning)
                        return;

                    result = EDSDK.EdsCreateEvfImageRef(pStream, out pImageEvf);
                    if (result != EDSDK.EDS_ERR_OK)
                    {
                        //Program.log(LogCategory.[Error], "Unable to create EvfImageRef:{0:X}", result)  
                        //MessageBox.Show("Unable to create EvfImageRef")  
                        //cmd.result = False  
                        logger.Error("On LiveView(), EDSDK.EdsCreateEvfImageRef(pStream, out pImageEvf)--> returns err=" + result.ToString());
                        ////////Dialogs.Error("EdsCreateEvfImageRef failed");

                        EDSDK.EdsRelease(pStream);
                        UpdateSpinner(false);
                        return;
                    }

                    if (!LiveViewRunning)
                        return;

                    result = EDSDK.EdsDownloadEvfImage(pCamera, pImageEvf);
                    if (result != EDSDK.EDS_ERR_OK)
                    {
                        int counter = 0;
                        while (result == EDSDK.EDS_ERR_OBJECT_NOTREADY && counter < 5)
                        {
                            Thread.Sleep(1000);
                            result = EDSDK.EdsDownloadEvfImage(pCamera, pImageEvf);
                            counter++;
                        }

                        counter = 0;
                        while (result == EDSDK.EDS_ERR_DEVICE_BUSY && counter < 5)
                        {
                            Thread.Sleep(1000);
                            result = EDSDK.EdsDownloadEvfImage(pCamera, pImageEvf);
                            counter++;
                        }

                        if (result != EDSDK.EDS_ERR_OK)
                        {
                            logger.Error("On LiveView(), EDSDK.EdsDownloadEvfImage(pCamera, pImageEvf)--> returns err=" + result.ToString());
                            //Program.log(LogCategory.[Error], "Unable to download Evf image:{0:X}", result)  
                            ////////Dialogs.Error("EdsDownloadEvfImage failed");

                            EDSDK.EdsRelease(pStream);
                            EDSDK.EdsRelease(pImageEvf);

                            UpdateSpinner(false);
                            return;
                        }
                    }

                    //Program.log(LogCategory.Debug, "Downloaded Evf image data.")  

                    // extract image data into   

                    if (!LiveViewRunning)
                        return;

                    IntPtr ipData = default(IntPtr);
                    result = EDSDK.EdsGetPointer(pStream, out ipData);
                    if (result != EDSDK.EDS_ERR_OK)
                    {
                        //Program.log(LogCategory.[Error], "EdsGetPointer failed: {0:X}", result)  

                        logger.Error("On LiveView(), EDSDK.EdsGetPointer(pStream, out ipData)--> returns err=" + result.ToString());
                        ////////Dialogs.Error("EdsGetPointer failed");

                        EDSDK.EdsRelease(pStream);
                        EDSDK.EdsRelease(pImageEvf);

                        UpdateSpinner(false);
                        return;
                    }

                    if (!LiveViewRunning)
                        return;

                    uint len = 0;
                    result = EDSDK.EdsGetLength(pStream, out len);
                    if (result != EDSDK.EDS_ERR_OK)
                    {
                        //Program.log(LogCategory.[Error], "EdsGetLength failed:{0:X}", result)  

                        logger.Error("On LiveView(), EDSDK.EdsGetLength(pStream, out len)--> returns err=" + result.ToString());
                        ////////Dialogs.Error("EdsGetLength failed");

                        EDSDK.EdsRelease(pStream);
                        EDSDK.EdsRelease(pImageEvf);
                        EDSDK.EdsRelease(ipData);

                        UpdateSpinner(false);
                        return;
                    }

                    byte[] buffer = new byte[Convert.ToInt32(len) + 1];

                    System.Runtime.InteropServices.Marshal.Copy(ipData, buffer, 0, Convert.ToInt32(len));
                    System.IO.MemoryStream memStream = new System.IO.MemoryStream(buffer);

                    // get the bitmap  
                    Bitmap tempImage = (Bitmap)Bitmap.FromStream(memStream);
                    Bitmap bitmap = new Bitmap(tempImage);
                    tempImage.Dispose();

                    if (!LiveViewRunning)
                    {
                        if (picboxPhoto.Image != null)
                        {
                            picboxPhoto.Image.Dispose();
                            picboxPhoto.Image = null;
                        }
                        return;
                    }
                    picboxPhoto.Image = bitmap;

                    // cleanup  
                    memStream.Dispose();
                    EDSDK.EdsRelease(pStream);
                    EDSDK.EdsRelease(pImageEvf);

                    EDSDK.EdsRelease(ipData);

                }

                if (picboxPhoto.Image != null)
                {
                    picboxPhoto.Image.Dispose();
                    picboxPhoto.Image = null;
                }
            }
            catch (Exception exc)
            {
                logger.Error(exc.StackTrace);
            }
        }


        #endregion LiveView

        #region BackgroundWorker

        private void bgWorker_DoWork_TakePicture(object sender, DoWorkEventArgs e)
        {
            logger.Info("On bgWorker_DoWork_TakePicture");
            int counter = 5;

            while (counter > 0)
            {
                UpdateCounterText(counter.ToString());
                counter--;
                Thread.Sleep(1000);
            }
            UpdateCounterText("");


            //Stop Live View 
            LiveViewRunning = false;
        }

        private void bgWorker_Completed_TakePicture(object sender, RunWorkerCompletedEventArgs e)
        {
            logger.Info("On bgWorker_Completed_TakePicture");

            bgWorker.DoWork -= bgWorker_DoWork_TakePicture;
            bgWorker.RunWorkerCompleted -= bgWorker_Completed_TakePicture;

            this.btnTakePicture.BackgroundImage = global::MarqueeMoment.Properties.Resources.take_picture_bttn_324_512;
            try
            {
                if (picboxPhoto.Image != null)
                {
                    picboxPhoto.Image.Dispose();
                    picboxPhoto.Image = null;
                }
                logger.Info("Call method controller.actionPerformed(takepicture)");
                controller.actionPerformed("takepicture");
                if (picboxPhoto.Image != null)
                {
                    picboxPhoto.Image.Dispose();
                    picboxPhoto.Image = null;
                }

            }
            catch (Exception exc)
            {
                logger.Error(exc.StackTrace);
                Dialogs.Error("Error in taking picture from camera, please connect camera properly and try again");
            }
            finally
            {
                this.Enabled = true;          
            }
        }
      
        #endregion BackgroundWorker
    }
}
